package net.bat.filter;

import java.lang.reflect.Field;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.LinkedHashMap;
import java.util.Map;

import org.springframework.data.domain.Sort;
import org.springframework.data.domain.Sort.Direction;
import org.springframework.data.domain.Sort.Order;
import org.springside.modules.persistence.SearchFilter;
import org.springside.modules.persistence.SearchFilter.Operator;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.common.collect.Maps;

public class ExtReq {
	public enum Oper {
		EQ, LIKE, GT, LT, GE, LE
	}

	private static final SimpleDateFormat fmt_date = new SimpleDateFormat("MM/dd/yyyy");

	private ObjectMapper mapper = new ObjectMapper();

	public Map<String, SearchFilter> parseFilter(String filter) throws Exception {
		Map<String, SearchFilter> sfm = Maps.newHashMap();
		if (filter == null) {
			return sfm;
		}
		ExtJSFilter[] fliters = mapper.readValue(filter, ExtJSFilter[].class);
		for (ExtJSFilter ef : fliters) {
			String filedName = ef.getProperty();
			SearchFilter sf = new SearchFilter(filedName, Operator.valueOf(ef.getOperator().toUpperCase()),
					ef.getValue());
			sfm.put(filedName, sf);
		}
		return sfm;
	}

	public Sort parseSort(String sort) throws Exception {
		if (sort == null) {
			return null;
		}
		ExtJSSort[] sorts = mapper.readValue(sort, ExtJSSort[].class);
		Order[] os = new Order[sorts.length];
		int pos = 0;
		for (ExtJSSort es : sorts) {
			String filedName = es.getProperty();
			Order so = new Order(Direction.valueOf(es.getDirection().toUpperCase()), filedName);
			os[pos++] = so;
		}
		return new Sort(os);
	}

	public <T> JPAReq parse(String filter, String sort, Class<T> cls) throws Exception {
		JPAReq req = new JPAReq();
		if (filter != null) {
			StringBuffer sbuf = new StringBuffer();
			int pos = 0;
			ExtJSFilter[] fliters = mapper.readValue(filter, ExtJSFilter[].class);
			Object[] queryParams = new Object[fliters.length];
			for (ExtJSFilter ef : fliters) {
				String filedName = ef.getProperty();
				if (pos == 0) {
					sbuf.append(" " + filedName);
				} else {
					sbuf.append(" and " + filedName);
				}
				Oper oper = Oper.valueOf(ef.getOperator().toUpperCase());
				Object val = ef.getValue();
				// EQ, LIKE, GT, LT, GTE, LTE
				switch (oper) {
				case EQ:
					sbuf.append(" =?");
					break;
				case LIKE:
					sbuf.append(" like ?");
					val = "%" + val + "%";
					break;
				case GT:
					sbuf.append(" >?");
					break;
				case LT:
					sbuf.append(" <?");
					break;
				case GE:
					sbuf.append(" >=?");
					break;
				case LE:
					sbuf.append(" <=?");
					break;
				}
				// 如果参数值与目标属性不匹配,需要特殊处理,例如：日期
				Field f = cls.getDeclaredField(filedName);
				Class<?> fcl = f.getType();
				if (!fcl.isAssignableFrom(val.getClass())) {
					if (fcl.isAssignableFrom(Date.class)) {
						// val = fmt_date.parse(val.toString());
						// dateformat: time
						val = new Date(Long.parseLong(val.toString()));
					}
				}
				queryParams[pos++] = val;
			}
			req.setWhereql(sbuf.toString());
			req.setQueryParams(queryParams);
		}
		if (sort != null) {
			LinkedHashMap<String, String> orderby = new LinkedHashMap<String, String>();
			ExtJSSort[] sorts = mapper.readValue(sort, ExtJSSort[].class);
			for (ExtJSSort es : sorts) {
				orderby.put(es.getProperty(), es.getDirection());
			}
			req.setOrderby(orderby);
		}
		return req;
	}
}
